/*
 * FibActor.java
 *
 * Created on May 29, 2005, 4:16 PM
 */

package aa.application.Fibonacci;

/**
 *
 * @author  xinghuizhao
 */


import aa.core.Actor;
import aa.core.ActorName;
import aa.core.CreateActorException;

/**
 * This class represents the fibonacci example actor.
 *
 *
 * @author  xinghuizhao
 */
public class FibActor extends Actor{
    
    int numResponses; //number of response it has received if it is fib actor
    
    int partialResponse; 
    
    /** The first response we have received from a child fib actor. We save
     *  this value until we receive the second response, and send our clint 
     *  the sum of both values 
     */
    
    ActorName client; //the actor which is suppose to receive result from this actor
    
    String meth; //method to invoke on teh receiving client (if this is a worker fib actor)
    
    /** Creates a new instance of FibActor */
    
    public FibActor(){
        
    }
    
    public FibActor(ActorName p_anClient,String p_strMeth) {
        client = p_anClient;
        meth = p_strMeth;
        numResponses = 0;
    }
    
    /** This method is called by a client to request a fib computation.
     * p_intVal : fibonacci number should be computed.
     * p_anClient : ActorName of the client waiting for a response.
     * p_strMeth : name of the method to be invoked on the client.
     *
     */
    
    public void fib(Integer p_intVal,ActorName p_anClient,String p_strMeth){
        int theVal=p_intVal.intValue();
        ActorName newChild=null;
        
        if (theVal==0){
            send(p_anClient,p_strMeth,new Integer(0));
        } 
        else if (theVal<3){
            send(p_anClient,p_strMeth,new Integer(1));
        } 
        else {//calculation
            
            try{
                newChild=create("aa.application.Fibonacci.FibActor",p_anClient,p_strMeth);
            }catch (CreateActorException e){
                
            }
            
            fib(new Integer(theVal-1),newChild,"result");
            
            fib(new Integer(theVal-2),newChild,"result");
            
        }
        
    }
    
    /** This method is called from another child actor to pass a partial result.
     *  We wait until we have two such results, add them, and return the result to 
     *  client.
     *
     */
    
    public void result(Integer p_intVal){
        if (numResponses==0){
            numResponses++;
            partialResponse = p_intVal.intValue();
        }
        else {
            //send the answer
        	   int resultNum = p_intVal.intValue()+partialResponse;
            send(client,meth,new Integer(p_intVal.intValue()+partialResponse));           
            System.out.println("actor ["+getActorName()+"] reports result  to actor ["+client+"] : " +resultNum);
            destroy("Result actor no longer accessible, removing...");
        }
    }
    
}
